home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / structs.c < prev    next >
Text File  |  1991-01-25  |  14KB  |  429 lines

  1. /*************************************************************************
  2.     This program is a demonstration of using arrays of structures
  3.     for such tasks as screen painting, field definition, and data file
  4.     searching.
  5.  
  6.     This program is submitted as public domain.  It's basic concept is
  7.     to communicate some uses of data structures and re-useable coding.
  8.     This program (along with other BTree and similiar structure based
  9.     programs) is the result of a C programming part II class I taught
  10.     at a local university.  Several of my students have stated how much
  11.     easier project developement was with routines similiar to these.
  12.  
  13.     Mario Giannini
  14.     Compuserve #76276,1576
  15.     January 25, 1991
  16. *************************************************************************/
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <conio.h>
  20. #include <io.h>
  21. #include <fcntl.h>
  22. #include <sys\types.h>
  23. #include <sys\stat.h>
  24. #include <dos.h>
  25. #include <malloc.h>   /* alloc.h for TurboC */
  26. #include <string.h>
  27. /*************************************************************************/
  28.                  /* Key macros to make life easier   */
  29. #define   ESC      0x1B
  30. #define   F10      0x4400
  31. #define   CURUP    0x4800
  32. #define   CURDN    0x5000
  33. #define   BACKSPACE 0x0008
  34. #define   ENTER     0x000D
  35.  
  36. #define  TextColor 7
  37. #define  DataColor 0xF
  38.  
  39. #define INDEXFLD 0x0001
  40.                          /* Here are our basic data structure definitions */
  41. typedef struct {
  42.     int H, V, Len, Option, Type, FieldNum;
  43.     char *Text, *Data;
  44.     } FIELDS;
  45.  
  46. typedef struct {
  47.     int Handle, RecSize;
  48.     FIELDS *EditFields;
  49.     char *Filename, *RecSpace;
  50.     long Recpos;
  51.     } RECORD;
  52.  
  53. /*************************************************************************/
  54. /* Here are data declarations, it should be noted that the record types
  55. **      can be changed here, and upon re-compile all of the code should
  56. **      still work as always, interpreting the structures themselves
  57. **/
  58.  
  59. FIELDS PersonFields[]={
  60.        0, 0, 10, 0, 0,        0, "First",   NULL,
  61.       25, 0, 10, 0, INDEXFLD, 0, "Last",    NULL,
  62.        0, 2, 35, 0, 0,        0, "Company", NULL,
  63.        0, 3, 35, 0, 0,        0, "Comment", NULL,
  64.        0, 0,  0, 0, 0, 0, NULL,      NULL};  /* NULL for Text is terminator */
  65.  
  66. RECORD Person={0, 0, PersonFields, "PERSON.DAT", NULL, 0L};
  67.  
  68.  FIELDS TransFields[]={
  69.        0, 0,  8, 0,   0, 0, "Date",   NULL,
  70.       25, 0, 10, 0,   0, 0, "Amount", NULL,
  71.         0, 0,  0, 0,   0, 0, NULL,     NULL};  /* NULL for Text is terminator */
  72. RECORD Transaction={0, 0, TransFields, "TRANS.DAT", NULL,0L};
  73.  
  74. /*************************************************************************/
  75. /* Sort of a 'main menu' of tables we can edit */
  76. RECORD *AllRecords[]={&Person, &Transaction, NULL};
  77. /*************************************************************************/
  78. /****      Function prototypes   ***/
  79. void  main(void);
  80. void AddItem(RECORD *Record);
  81. void EditItem(RECORD *Record);
  82. int  EditRecord(RECORD *Record);
  83. void ShowScreen(RECORD *Record);
  84. void ShowData(RECORD *Record);
  85. void Cls(int  Color);
  86. void Locate(int  H,int  V);
  87. void PrintStr(char  *Str,int  Color);
  88. void Message(char  *Str,int  Wait);
  89. int  MyGets(char  *Dest,int  Len);
  90. int  GetKey(void);
  91. int  AppendRecord(RECORD *Record);
  92. int  LocateRecord(RECORD *Rec);
  93. int  ReadRecord(RECORD *Record);
  94. int  WriteRecord(RECORD *Record);
  95. void BlankRecord(RECORD *Record);
  96. int  OpenFile(RECORD *Record);
  97. void CloseFile(RECORD *Record);
  98. /*************************************************************************/
  99. /***  Start of code section                                            ***/
  100. /***                                                                   ***/
  101. /*************************************************************************/
  102. void main(void)
  103. {
  104.     int i, NumOfRecs, Ch=0, Ch2;
  105.  
  106.     while(Ch!=ESC)
  107.     {
  108.         Cls(7);
  109.         for(NumOfRecs=0;AllRecords[NumOfRecs];NumOfRecs++)
  110.             printf("%d: %s\n", NumOfRecs+1, AllRecords[NumOfRecs]->Filename);
  111.         printf("\nESC to quit.\n\nPlease press a key..");
  112.         do {
  113.             Ch=GetKey();
  114.         } while(Ch!=ESC && (Ch<'0'||Ch-'1'>NumOfRecs));
  115.         if(Ch==ESC)
  116.             continue;
  117.         Cls(7);
  118.         printf("You Selected %s\n\n", AllRecords[Ch-'1']->Filename);
  119.         printf("A) Add\nE) Edit\n\nESC for previous menu\n\nMake selection:");
  120.         do {
  121.             Ch2=getch();
  122.             Ch2=toupper(Ch2);
  123.         } while( Ch2!=ESC && Ch2!='A' && Ch2!='E') ;
  124.  
  125. /*
  126. ** Note how the AllRecord array is used to process table based on user
  127. **      selection.
  128. */
  129.         if(Ch2=='A')
  130.             AddItem(AllRecords[Ch-'1']);
  131.         if(Ch2=='E')
  132.             EditItem(AllRecords[Ch-'1']);
  133.     }
  134.     
  135. }
  136. /*************************************************************************/
  137. /***  Higher-level functions                                           ***/
  138. /***                                                                   ***/
  139. /*************************************************************************/
  140. void AddItem(RECORD *Record)
  141. {
  142.     Cls(7);
  143.     OpenFile(Record);
  144.     ShowScreen(Record);
  145.     BlankRecord(Record);
  146.     Message("Press ESC to Abort, F10 to Add",0);
  147.     if(EditRecord(Record)==F10)
  148.         AppendRecord(Record);
  149.     CloseFile(Record);
  150.     Message("", 0);
  151. }
  152. /*************************************************************************/
  153. void EditItem(RECORD *Record)
  154. {
  155.     Cls(7);
  156.     OpenFile(Record);
  157.     ShowScreen(Record);
  158.     BlankRecord(Record);
  159.     Message("Press ESC to Abort, F10 to start search",0);
  160.     if(EditRecord(Record)==F10)
  161.     {
  162.         if(LocateRecord(Record))
  163.         {
  164.             Message("Press ESC to abort, F10 to save updates", 0);
  165.             ReadRecord(Record);
  166.             ShowData(Record);
  167.             if(EditRecord(Record)==F10)
  168.                 WriteRecord(Record);
  169.         }
  170.         else
  171.             Message("Criteria not found. Press any key to continue",1);
  172.     }
  173.     CloseFile(Record);
  174.     Message("",0);
  175. }
  176. /*************************************************************************/
  177. /***  ScreenI/O section follows                                        ***/
  178. /***                                                                   ***/
  179. /*************************************************************************/
  180. int EditRecord(RECORD *Record)   /* Edits a Record  */
  181. {
  182.     int i=0, Ch=0, LastEntry=0;
  183.  
  184. /*
  185. ** Note how this founction interprets whatever structures are passed
  186. **     to it at run-time.  Not much is hard-coded.
  187. */
  188.     for(LastEntry=0;Record->EditFields[LastEntry].Text;LastEntry++)
  189.         ;
  190.     while(Ch!=ESC && Ch!=F10)
  191.     {
  192.         Locate(Record->EditFields[i].H+strlen(Record->EditFields[i].Text)+1,
  193.             Record->EditFields[i].V);
  194.         Ch=MyGets(Record->EditFields[i].Data, Record->EditFields[i].Len);
  195.         if( (Ch==ENTER||Ch==CURDN) && ++i>=LastEntry)
  196.             i=0;
  197.         if(Ch==CURUP && --i<0)
  198.             i=LastEntry-1;
  199.     }
  200.     return(Ch);
  201. }
  202. /****************************************************************/
  203. void ShowScreen(RECORD *Record)   /* Show Screen layout Data  */
  204. {
  205.     int i=0;
  206.  
  207.     for(i=0;Record->EditFields[i].Text;i++)
  208.     {
  209.         Locate(Record->EditFields[i].H, Record->EditFields[i].V);
  210.         PrintStr(Record->EditFields[i].Text, TextColor);
  211.     }
  212. }
  213. /****************************************************************/
  214. void ShowData(RECORD *Record)   /* Show Record Data  */
  215. {
  216.     int i=0;
  217.  
  218.     for(i=0;Record->EditFields[i].Text;i++)
  219.     {
  220.         Locate(Record->EditFields[i].H+strlen(Record->EditFields[i].Text)+1, 
  221.             Record->EditFields[i].V);
  222.         PrintStr(Record->EditFields[i].Data, DataColor);
  223.     }
  224. }
  225. /****************************************************************/
  226. void Cls(int Color)      /* Clears the screen to any color */
  227. {
  228.     union REGS Regin;
  229.  
  230.     Regin.x.ax=0x0600;
  231.     Regin.h.bh=(char)Color;
  232.     Regin.x.cx=0;
  233.     Regin.x.dx=0x1950;
  234.     int86(0x10, &Regin, &Regin);
  235.     Locate(0,0);
  236. }
  237. /****************************************************************/
  238. void Locate(int H, int V)  /* Locate cursor at an Horiz, Vert coordinate */
  239. {
  240.     union REGS Regin;
  241.     Regin.h.ah=2;
  242.     Regin.h.bh=0;
  243.     Regin.h.dh=(char)V;
  244.     Regin.h.dl=(char)H;
  245.     int86(0x10, &Regin, &Regin);
  246. }
  247. /****************************************************************/
  248. void PrintStr(char *Str, int Color) /* Generic color print string routine */
  249. {
  250.     union REGS Regin;
  251.  
  252.     Regin.h.ah=9;
  253.     Regin.h.al=*Str;
  254.     Regin.x.cx=strlen(Str);
  255.     Regin.h.bl=(char)Color;
  256.     Regin.h.bh